package mh.lightremote;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.UUID;

import android.app.Activity;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.SystemClock;
import android.widget.Toast;

public class BTController extends Service {
	protected static final int REQUEST_ENABLE_BT = 1;
	
	private BluetoothAdapter localAdapter = BluetoothAdapter.getDefaultAdapter();
	private BluetoothDevice btDevice;
	private BluetoothSocket btSocket;

	private final UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
	private String currentMAC;

	private OutputStream outputStream;
	public OutputStream getOutputStream() {
		return outputStream;
	}
	
	private InputStream inputStream;
	private BufferedReader bufferedReader;
	private Queue<String> messageQueue = new LinkedList<String>();
	public Queue<String> getMessageQueue() {
		return messageQueue;
	}

	private boolean connected = false;
	public boolean isConnected() {
		return connected;
	}
	
	
	private Thread listener = new Thread( new Runnable() {
		
		@Override
		public void run() {
			while( true ) {
				try {
					final String buffer = bufferedReader.readLine();
					
					if( buffer != null ) {
						//handler.post( new Runnable() {
							
							//@Override
							//public void run() {
								//Toast.makeText( BTController.this, "Msg from device: " + buffer, Toast.LENGTH_SHORT ).show();
								messageQueue.add( buffer );
							//}
						//});
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	});
	
	public boolean checkConnection() {
		if( connected == true ) {
			messageQueue.clear();
			
			try {
				outputStream.write( "ping\n".getBytes("ASCII") );
				outputStream.flush();
			} catch (IOException e) {
				return false;
			}
			
			long start = SystemClock.uptimeMillis();
			while( messageQueue.isEmpty() ) {
				if( SystemClock.uptimeMillis() > start + 1000 ) {
					break;
				}
			}
			
			if( !messageQueue.isEmpty() ) {
				String message = messageQueue.poll();
				if( message.equals( "pong") ) {
					return true;
				}
			}
		}
		
		return false;
	}
	
    @Override
    public void onCreate() {
    	Toast.makeText(this, "BTService stated.", Toast.LENGTH_SHORT).show();
    	
    	super.onCreate();
    }
    
    @Override
    public void onDestroy() {
    	Toast.makeText(this, "BTService stoped.", Toast.LENGTH_SHORT).show();
    	
    	close();
    	
    	super.onDestroy();
    }
	
	public void connect( String deviceMAC ) throws IOException {
		currentMAC = deviceMAC;
		
		btDevice = localAdapter.getRemoteDevice( deviceMAC );
		btSocket = btDevice.createRfcommSocketToServiceRecord( uuid );

		btSocket.connect();
		
		outputStream = btSocket.getOutputStream();
		
		inputStream = btSocket.getInputStream();
		bufferedReader = new BufferedReader( new InputStreamReader( inputStream, "ASCII" ) );
		if( listener.getState() == Thread.State.NEW ) {
			listener.start();
		}
		
		connected = true;
	}
	
//	public void reConnect() throws IOException {
//		if( currentMAC != null ) {
//			connect( currentMAC );
//		} else {
//			throw new IllegalStateException( "No previous connection." );
//		}
//	}
	
    public void close() {
    	connected = false;
    	
    	if( btSocket != null ) {
			try {
				btSocket.close();
			} catch (IOException e) {
	
			}
    	}
    }
	
	public Set<BluetoothDevice> getBondedDevices() {
		return this.localAdapter.getBondedDevices();
	}
	
	public boolean isEnabled() {
		return localAdapter.isEnabled();
	}
	
	public void enable() {
		localAdapter.enable();
	}

	
    public void setupConnection( Activity activity ) {
    	if( isConnected() ) {
    		return;
    	}
    	
	    if( isEnabled() ) {
        	try {
				connect( "00:12:6F:22:53:78" );
				Toast.makeText(activity.getBaseContext(), "Connected to Device.", Toast.LENGTH_SHORT).show();
				Thread.currentThread().sleep( 500 );
			} catch (IOException e) {
				Toast.makeText(activity.getBaseContext(), "Can't connected to Device.", Toast.LENGTH_SHORT).show();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
        } else {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            activity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }
    }
    
    public static class DefaultBTServiceConnection implements ServiceConnection {
    	Activity activity;
    	
		BTController bTController;
		public BTController getBTController() {
			return bTController;
		}
		
	
		public DefaultBTServiceConnection( Activity activity ) {
			this.activity = activity;
		}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			bTController = ((BTController.LocalBinder)service).getService();
			
			Toast.makeText(activity, "Connected to BTService.", Toast.LENGTH_SHORT).show();
			
			bTController.setupConnection( activity );
			
			Toast.makeText(activity, "Connection: " + bTController.checkConnection(), Toast.LENGTH_SHORT).show();
		}
		
		@Override
		public void onServiceDisconnected(ComponentName name) {
			bTController = null;
			
			Toast.makeText(activity, "Disconnected from BTService.", Toast.LENGTH_SHORT).show();
		}
    }
	
    public class LocalBinder extends Binder {
    	BTController getService() {
            return BTController.this;
        }
    }		
	private final IBinder binder = new LocalBinder();
	
	@Override
	public IBinder onBind( Intent intent ) {
		return binder;
	}
}